-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[JENKINS-63343] Validate element types for collections and maps when deserializing XML files #9727
Conversation
core/src/test/java/hudson/util/RobustCollectionConverterTest.java
Outdated
Show resolved
Hide resolved
// TODO: Is there a better way to make something like this work? Does it break any custom converters? | ||
if (converter == null && new RobustCollectionConverter(mapper, reflectionProvider).canConvert(type)) { | ||
converter = new RobustCollectionConverter(mapper, reflectionProvider, field.getGenericType()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In particular I am wondering about things like NodeList and AxisList which extend ArrayList
. They might be ok because of the exact equality comparisons here, but I am not sure. I guess also that those classes don't support any of the desired recoverability features in RobustCollectionConverter
, but that shouldn't be affected by my PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I confirmed that NodeList
is unaffected by this change - its custom converter continues to be used and its deserialization is not robust against invalid values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at #342, I think we only expect getLocalConverter
to matter for fields that have the @XStreamConverter
annotation, which seems to be more or less unused based on this search, and also none of those annotations are for collections or maps.
@@ -451,6 +451,13 @@ private boolean fieldDefinedInClass(Object result, String attrName) { | |||
|
|||
protected Object unmarshalField(final UnmarshallingContext context, final Object result, Class type, Field field) { | |||
Converter converter = mapper.getLocalConverter(field.getDeclaringClass(), field.getName()); | |||
if (converter == null) { | |||
if (new RobustCollectionConverter(mapper, reflectionProvider).canConvert(type)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit awkward to recreate this for every single field being unmarshalled, should we keep an instance as a local field just for these canConvert
calls?
@@ -451,6 +451,13 @@ private boolean fieldDefinedInClass(Object result, String attrName) { | |||
|
|||
protected Object unmarshalField(final UnmarshallingContext context, final Object result, Class type, Field field) { | |||
Converter converter = mapper.getLocalConverter(field.getDeclaringClass(), field.getName()); | |||
if (converter == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #9727 (comment) for discussion about cases where converter
is not null. In short, I don't think we care.
I am not sure though whether this method covers all of the cases we care about. It seems like we may need similar changes related to "implicit collections". I will look into that a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically, prior to this line, I think we should look up the field and then add code comparable to what we added to RobustCollectionConverter
to validate the value type:
collection.add(value); |
Needs to be investigated with a test case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into the cases related to implicit collections today. My understanding is that you need to explicitly call addImplicitArray
, addImplicitCollection
, or addImplicitMap
for the relevant code to matter, which is not very common, see here (there are also a few usages in CloudBees plugins). The overloads where you specify the item type already avoid JENKINS-63343 because of getFieldNameForItemTypeAndName
here which uses context.getRequiredType()
leading to invalid elements being silently ignored. The overloads for arrays and maps seem to not actually work at all due to this check (which leaves me somewhat confused about #2621, but perhaps my testing did not cover all cases).
So, I think we do not really care much about implicit collections, but 09ca355 should handle them too.
RobustCollectionConverter
in some casesThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments, but generally looks good to the extent I understand it; I definitely do not follow all the subtleties about XStream behavior.
/label ready-for-merge This PR is now ready for merge, after ~24 hours, we will merge it if there's no negative feedback. Thanks! |
See JENKINS-63343. This PR checks all fields being deserialized to see if they will be handled by
RobustCollectionConverter
orRobustMapConverter
, and if so, it explicitly constructs an instance of the converter specialized to the type of the field in question so that collection elements and map keys and values can be type checked. Any values which do not have the expected type are ignored, and anOldDataMonitor
warning is logged.Testing done
See new automated tests.
Proposed changelog entries
Proposed upgrade guidelines
N/A
Submitter checklist
Desired reviewers
@mention
Before the changes are marked as
ready-for-merge
:Maintainer checklist